﻿using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;

namespace NDK.Module.BLL
{
    public static class RedisUtils
    {
        private static readonly ConfigurationOptions ConfigurationOptions = ConfigurationOptions.Parse("192.168.10.3:6379");
        private static readonly object Locker = new object();
        private static ConnectionMultiplexer _redisConn;

        private const double timeout = 3600;

        public delegate void RedisDeletegate(string str);
        public static event RedisDeletegate RedisSubMessageEvent;

        /// <summary>
        /// 订阅
        /// </summary>
        /// <param name="subChannel"></param>
        public static void RedisSub(string subChannel)
        {

            RedisConn.GetSubscriber().Subscribe(subChannel, (channel, message) =>
            {
                RedisSubMessageEvent?.Invoke(message); //触发事件
            });

        }


        /// <summary>
        /// 发布
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="channel"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static long RedisPub<T>(string channel, T msg)
        {
            return RedisConn.GetSubscriber().Publish(channel, JsonConvert.SerializeObject(msg));
        }

        /// <summary>
        /// 删除发布
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="channel"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static void RedisUnSub<T>(string channel, T msg)
        {
             RedisConn.GetSubscriber().Unsubscribe(channel);
        }
        ////  private static void RedisSubMessageEvent(string msg)
        ////{
        //RedisUtils.RedisSubMessageEvent += RedisSubMessageEvent;
        //    RedisUtils.RedisSub("sn1234");
        //    Console.Write($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")} RedisSubMessageEvent: {msg}");
        //}

        //private void button2_Click(object sender, EventArgs e)
        //{
        //    RedisUtils.RedisPub("sn1234", 111111);
        //}

        /// <summary>
        /// 单例获取
        /// </summary>
        public static ConnectionMultiplexer RedisConn
        {
            get
            {
                if (_redisConn == null)
                {
                    // 锁定某一代码块，让同一时间只有一个线程访问该代码块
                    lock (Locker)
                    {
                        if (_redisConn == null || !_redisConn.IsConnected)
                        {
                            _redisConn = ConnectionMultiplexer.Connect(ConfigurationOptions);
                        }
                    }
                }
                return _redisConn;
            }


        }

        public static bool getConn()
        {
            if (RedisConn == null)
                return false;
            else
                return true;

        }
        /// <summary>
        /// 删除指定key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool Delete(string key, int db = 0)
        {
            IDatabase dabase = RedisConn.GetDatabase(db);
            bool ret = dabase.KeyDelete(key);
            return ret;
        }
        /// <summary>
        /// 写入字符串value到key
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool SetString(string key, string value, int db = 0)
        {
            IDatabase dabase = RedisConn.GetDatabase(db);
            bool ret = dabase.StringSet(key, value);
            return ret;
        }
        /// <summary>
        /// 读取key对应的字符串value
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetString(string key, int db = 0)
        {
            IDatabase dabase = RedisConn.GetDatabase(db);
            string value = dabase.StringGet(key);
            return value;
        }


        public static bool GetStringList(string KeyPattern, out List<String> Results, int db = 0)
        {
            Results = new List<string>();
            var script = "return redis.call('keys',@pattern)";
            var prepared = LuaScript.Prepare(script);
            var cacheResult = RedisConn.GetDatabase(db).ScriptEvaluate(prepared, new { pattern = KeyPattern });
            if (cacheResult.IsNull)
            {
                return false;
            }
            var rest = (string[])cacheResult;
            Results = rest.ToList();
            return rest.Length > 0;
        }





    }
}
